package com.lenovo.smarttraffic.view;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
import android.widget.TextView;

public class SlideRecyclerView extends RecyclerView {
    private boolean isMoving;
    //滑动速度，滑动距离
    private static final int MINIMUM_VELOCITY = 500;
    private VelocityTracker mVelocityTracker;
    //最小滑动距离
    private int mTouchSlop;
    private Scroller mScroller;

    private ViewGroup mMoveView;
    private ViewGroup mLastView;

    private int mFirstX;
    private int mFirstY;
    private int mLastX;
    private int mItemwidth;

    public SlideRecyclerView(Context context) {
        super(context);
        init(context);
    }

    public SlideRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }


    public SlideRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        //最小滑动距离
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mScroller = new Scroller(context);

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();
        obtianVelocityTracter(e);
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                mFirstX = x;
                mFirstY = y;
                mLastX = x;
                mMoveView = (ViewGroup) findChildViewUnder(x, y);
                if (mLastView != null && mLastView.getScrollX() != 0 && mLastView != mMoveView) {
                    closeMenu();
                }
                if (mMoveView != null && mMoveView.getChildCount() >= 2) {
                    mItemwidth = mMoveView.getChildAt(1).getWidth();
                } else {
                    mItemwidth = -1;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.computeCurrentVelocity(1000);
                int moveX = Math.abs(x - mFirstX);
                int moveY = Math.abs(y - mFirstY);
                int velocityX = (int) Math.abs(mVelocityTracker.getXVelocity());
                int velocityY = (int) Math.abs(mVelocityTracker.getYVelocity());
                boolean isHoritalMove = ((velocityX > velocityY && velocityX >= MINIMUM_VELOCITY) ||
                        (moveX > moveY && moveX > mTouchSlop)) && mItemwidth != -1 && getScrollState() == 0;
                if (isHoritalMove) {
                    isMoving = true;
                    return true;
        }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                //不是横向滑动，子View点击事件，recyclerView纵向滑动
                releaseVelocityTracter();
                closeMenuNow();
                break;
            default:
                break;
        }
        return super.onInterceptTouchEvent(e);
    }


    @Override
    public boolean onTouchEvent(MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();
        obtianVelocityTracter(e);
        switch (e.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (isMoving) {
                    int dx = mLastX - x;
                    //一开始我的srollX==0，没有任何动作改变view位置
                    if (dx + mMoveView.getScrollX() <= mItemwidth && dx + mMoveView.getScrollX() >= 0) {
                        mMoveView.scrollBy(dx, 0);
                    }
                    mLastX = x;
                    return true;
                } else {
                    mVelocityTracker.computeCurrentVelocity(1000);
                    int moveX = Math.abs(x - mFirstX);
                    int moveY = Math.abs(y - mFirstY);
                    int velocityX = (int) Math.abs(mVelocityTracker.getXVelocity());
                    int velocityY = (int) Math.abs(mVelocityTracker.getYVelocity());
                    boolean isHoritalMove = ((velocityX > velocityY && velocityX >= MINIMUM_VELOCITY) ||
                            (moveX > moveY && moveX > mTouchSlop)) && mItemwidth != -1 && getScrollState() == 0;
                    if (isHoritalMove) {
                        int dx = mLastX - x;
                        if (dx + mMoveView.getScrollX() <= mItemwidth && dx + mMoveView.getScrollX() >= 0) {
                            mMoveView.scrollBy(dx, 0);
                        }
                        mLastX = x;
                        isMoving = true;
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (isMoving) {
                    if (!mScroller.isFinished()) {
                        //先前没完成的事情直接到达终点
                        mScroller.abortAnimation();
                        mLastView.scrollTo(mScroller.getFinalX(), 0);
                    }
                    isMoving = false;
                    mLastView = mMoveView;
                    mVelocityTracker.computeCurrentVelocity(1000);
                    int scrollX = mLastView.getScrollX();
                    if (mVelocityTracker.getXVelocity() >= MINIMUM_VELOCITY) {
                        mScroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX));
                    } else if (mVelocityTracker.getXVelocity() < -MINIMUM_VELOCITY) {
                        int dx = mItemwidth - scrollX;
                        mScroller.startScroll(scrollX, 0, dx, 0, Math.abs(mItemwidth - scrollX));
                    } else if (scrollX > mItemwidth / 2) {
                        int dx = mItemwidth - scrollX;
                        mScroller.startScroll(scrollX, 0, dx, 0, Math.abs(mItemwidth - scrollX));
                    } else {
                        mScroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX));
                    }
                    invalidate();
                } else if (mLastView != null && mLastView.getScrollX() != 0) {
                    //不是水平滑动则直接关闭
                    closeMenuNow();
                }
                releaseVelocityTracter();
                break;
            default:
                break;
        }
        return super.onTouchEvent(e);
    }


    private void closeMenu() {
        mScroller.startScroll(mLastView.getScrollX(), 0, -mLastView.getScrollX(), 0, 500);
        invalidate();
    }

    private void closeMenuNow() {
        if (mLastView != null && mLastView.getScrollX() != 0) {
            mLastView.scrollTo(0, 0);
        }
    }


    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            if (isInWindow(mLastView)) {
                    mLastView.scrollTo(mScroller.getCurrX(), 0);
                    invalidate();
            } else {
                mScroller.abortAnimation();
                mLastView.scrollTo(mScroller.getFinalX(), 0);
            }
        }

    }

    private boolean isInWindow(View lastView) {
        LayoutManager layoutManager = getLayoutManager();
        if (layoutManager instanceof LinearLayoutManager) {
            int firstPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            int lastPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            int position = layoutManager.getPosition(lastView);
            return position <= lastPosition && position >= firstPosition;
        }
        return true;
    }

    private void obtianVelocityTracter(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
    }

    private void releaseVelocityTracter() {
        if (mVelocityTracker != null) {
            mVelocityTracker.clear();
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }
}
